package net.csdn.business.search.facade;


import cn.hutool.core.collection.ListUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import net.csdn.business.common.domain.PageDto;
import net.csdn.business.common.domain.query.IssuePageQuery;
import net.csdn.business.common.domain.query.IssueSearchQuery;
import net.csdn.business.common.domain.query.RepoSearchQuery;
import net.csdn.business.common.domain.query.discuss.DiscussSearchQuery;
import net.csdn.business.common.domain.vo.IssueItemVO;
import net.csdn.business.common.domain.vo.IssueSearchVO;
import net.csdn.business.common.domain.vo.RepoSearchVO;
import net.csdn.business.common.domain.vo.discuss.DiscussSearchVO;
import net.csdn.business.common.enums.ResultCodeEnum;
import net.csdn.business.common.exception.BusinessException;
import net.csdn.business.framework.async.config.AsyncThreadPoolConfig;
import net.csdn.business.framework.audit.config.AuditStrategyConfig;
import net.csdn.business.search.config.SearchConfig;
import net.csdn.business.search.model.ElasticSearchRequest;
import net.csdn.business.search.model.QueryCommand;
import net.csdn.business.search.service.SearchService;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName SearchFacade
 * @Description 搜索
 * @Author zhangyl
 * @Date 2024/04/23 14:15
 */
@Slf4j
@Component
public class SearchFacade {
    @Autowired
    private SearchService searchService;
    @Autowired
    private AuditStrategyConfig auditStrategyConfig;

    private List<String> disCussSearchField;
    private List<String> issueSearchField;
    private List<String> repoSearchField;


    @PostConstruct
    public void initSearchFiled(){
        disCussSearchField=new ArrayList<>();
        disCussSearchField.add("title");
        disCussSearchField.add("content");
        issueSearchField=new ArrayList<>();
        issueSearchField.add("title");
        issueSearchField.add("content");
        repoSearchField=new ArrayList<>();
   /*   repoSearchField.add("name");
        repoSearchField.add("path");*/
        repoSearchField.add("name_with_namespace");
        repoSearchField.add("path_with_namespace");
        repoSearchField.add("description");
    }

    /**
     * 讨论搜素
     *
     * @param params 搜索相关参数
     * @return 搜索结果
     */
    public PageDto<DiscussSearchVO> discussSearch(DiscussSearchQuery params) throws Exception {
        String key=params.getKey();
        Boolean isTotal=params.getIsTotal();
        Integer sort=params.getSort();
        String sourceIdParams=params.getSourceId();
        Integer pageNum=params.getPageNum();
        Integer pageSize=params.getPageSize();
        List<DiscussSearchVO> data = new ArrayList<>();
        ElasticSearchRequest request = new ElasticSearchRequest();
        QueryCommand query = new QueryCommand();
        query.setIndexname("discuss");
        if (StringUtils.isBlank(key)) {
            query.setKeyWords("*");
        } else {
            query.setKeyWords(key);
        }
        if(!isTotal){
            query.setRows(pageSize);
            query.setStart((pageNum-1)*pageSize);
            Map<String, SortOrder> sortMap=new HashMap<>();
            switch (sort){
                case 1:
                    sortMap.put("comment_total", SortOrder.DESC);
                    break;
                case 2:
                    sortMap.put("like_total", SortOrder.DESC);
                    break;
                case 3:
                    sortMap.put("created_date", SortOrder.DESC);
                    break;
            }
            query.setSort(sortMap);
            query.setIsHighlight(true);
        }else{
            query.setRows(1);
            query.setStart(0);
        }
        query.setSearchField(disCussSearchField);
        request.setQuery(query);
        //过滤条件构造
        Map<String, List<String>> filter=new HashMap<>();
        //审核条件
        List<String> filterStatus= auditStrategyConfig.getCurrentVisible();
        filter.put("audit_status",filterStatus);
        //可见性：privacy：0：公开；1:私密
        List<String> privacy=new ArrayList<>();
        privacy.add("0");
        filter.put("privacy",privacy);
        //仓库或组织id限制
        if(StringUtils.isNotBlank(sourceIdParams)){
            List<String> sourceIds=new ArrayList<>();
            sourceIds.add(sourceIdParams);
            filter.put("source_id",sourceIds);
        }
        request.setFilter(filter);
        SearchResponse searchResponse = searchService.query_string(request);
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        if(isTotal){
            long total=hits.getTotalHits().value;
            return PageDto.build(data, pageNum, pageSize, total);
        }
        List<String> orgIds=new ArrayList<>();
        List<String> projectIds=new ArrayList<>();
        for (SearchHit hit : searchHits) {
            Map<String, Object> map = hit.getSourceAsMap();
            // 获取高亮结果，对原来字段进行替换
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            for (Map.Entry<String, HighlightField> entry : highlightFields.entrySet()) {
                String mapKey = entry.getKey();
                HighlightField mapValue = entry.getValue();
                Text[] fragments = mapValue.fragments();
                String fragmentString = fragments[0].string();
                map.put(mapKey, fragmentString);
            }
            DiscussSearchVO discussSearchVO = JSONUtil.toBean(JSON.toJSONString(map), DiscussSearchVO.class);
            Integer sourceType=discussSearchVO.getSourceType();
            String sourceId=discussSearchVO.getSourceId();
            switch (sourceType){
                case 1:
                    orgIds.add(sourceId);
                    break;
                case 2:
                    projectIds.add(sourceId);
                    break;
            }
            data.add(discussSearchVO);
        }
        long total=hits.getTotalHits().value;
        return PageDto.build(data, pageNum, pageSize, total);
    }


    public PageDto<IssueSearchVO> issueSearch(IssueSearchQuery params) throws Exception{
        Boolean isTotal=params.getIsTotal();
        String key=params.getKey();
        String sourceId=params.getSourceId();
        Integer sort=params.getSort();
        Integer pageNum=params.getPageNum();
        Integer pageSize=params.getPageSize();
        List<IssueSearchVO> data = new ArrayList<>();
        ElasticSearchRequest request = new ElasticSearchRequest();
        QueryCommand query = new QueryCommand();
        query.setIndexname("issue");
        if (StringUtils.isBlank(key)) {
            query.setKeyWords("*");
        } else {
            query.setKeyWords(key);
        }
        if(!isTotal){
            query.setRows(pageSize);
            query.setStart((pageNum-1)*pageSize);
            Map<String, SortOrder> sortMap=new HashMap<>();
            switch (sort){
                case 1:
                    sortMap.put("created_date", SortOrder.DESC);
                    break;
                case 2:
                    sortMap.put("created_date", SortOrder.ASC);
                    break;
            }
            query.setSort(sortMap);
            query.setIsHighlight(true);
        }else{
            query.setRows(1);
            query.setStart(0);
        }
        query.setSearchField(issueSearchField);
        request.setQuery(query);
        //过滤条件构造
        Map<String, List<String>> filter=new HashMap<>();
        //审核条件
        List<String> filterStatus= auditStrategyConfig.getCurrentVisible();
        filter.put("audit_status",filterStatus);
        //可见性：privacy：0：公开；1:私密
        List<String> privacy=new ArrayList<>();
        privacy.add("0");
        filter.put("privacy",privacy);
        //仓库限制
        if(StringUtils.isNotBlank(sourceId)){
            List<String> sourceIds=new ArrayList<>();
            sourceIds.add(sourceId);
            filter.put("project_id",sourceIds);
        }
        request.setFilter(filter);
        /*if (StringUtils.isNotBlank(startdate) || StringUtils.isNotBlank(enddate)) {
            FilterCommand filter = new FilterCommand();
            filter.setField("visittime");
            filter.setStartdate(startdate);
            filter.setEnddate(enddate);
            request.setFilter(filter);
        }*/
        SearchResponse searchResponse = searchService.query_string(request);
        SearchHits hits = searchResponse.getHits();
        if(isTotal){
            long total=hits.getTotalHits().value;
            return PageDto.build(data, pageNum, pageSize, total);
        }
        SearchHit[] searchHits = hits.getHits();
        List<String> projectIds=new ArrayList<>();
        for (SearchHit hit : searchHits) {
            Map<String, Object> map = hit.getSourceAsMap();
            // 获取高亮结果，对原来字段进行替换
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            for (Map.Entry<String, HighlightField> entry : highlightFields.entrySet()) {
                String mapKey = entry.getKey();
                HighlightField mapValue = entry.getValue();
                Text[] fragments = mapValue.fragments();
                String fragmentString = fragments[0].string();
                map.put(mapKey, fragmentString);
            }
            IssueSearchVO issueSearchVO = JSONUtil.toBean(JSON.toJSONString(map), IssueSearchVO.class);
            String projectId=issueSearchVO.getProjectId();
            projectIds.add(projectId);
            data.add(issueSearchVO);
        }
        long total=hits.getTotalHits().value;
        return PageDto.build(data, pageNum, pageSize, total);
    }


    public PageDto<IssueItemVO> searchByProject(IssuePageQuery params) throws Exception{
        Boolean isTotal=params.getIsTotal();
        List<String> projectIds=params.getProjectIds();
        if(projectIds==null||projectIds.size()==0){
            throw new BusinessException(ResultCodeEnum.PARAMETER_ERROR_CUSTOM,"projectIds");
        }
        String key=params.getKey();
        Integer sort=params.getOrder();
        Integer pageNum=params.getPageNum();
        Integer pageSize=params.getPageSize();
        List<IssueItemVO> data = new ArrayList<>();
        ElasticSearchRequest request = new ElasticSearchRequest();
        QueryCommand query = new QueryCommand();
        query.setIndexname("issue");
        if (StringUtils.isBlank(key)) {
            query.setKeyWords("*");
        } else {
            query.setKeyWords(key);
        }
        if(!isTotal){
            query.setRows(pageSize);
            query.setStart((pageNum-1)*pageSize);
            Map<String, SortOrder> sortMap=new HashMap<>();
            switch (sort){
                case 1:
                    sortMap.put("updated_date", SortOrder.DESC);
                    break;
                case 2:
                    sortMap.put("updated_date", SortOrder.ASC);
                    break;
                case 3:
                    sortMap.put("created_date", SortOrder.DESC);
                    break;
                case 4:
                    sortMap.put("created_date", SortOrder.ASC);
                    break;
            }
            query.setSort(sortMap);
        }else{
            query.setRows(1);
            query.setStart(0);
        }
        query.setSearchField(issueSearchField);
        request.setQuery(query);
        //过滤条件构造
        Map<String, List<String>> filter=new HashMap<>();
        //审核条件
        List<String> filterStatus= auditStrategyConfig.getCurrentVisible();
        filter.put("audit_status",filterStatus);
        //可见性：privacy：0：公开；1:私密
        List<String> privacy=new ArrayList<>();
        privacy.add("0");
        filter.put("privacy",privacy);
        //仓库限制
        filter.put("project_id",projectIds);
        //id限制
        List<String> issueIds=params.getIssueIds();
        if(issueIds!=null&&issueIds.size()>0){
            filter.put("id",issueIds);
        }
        //issue优先级
        List<String> prioritys=params.getPrioritys();
        if(prioritys!=null&&prioritys.size()>0){
            filter.put("priority",prioritys);
        }
        //按负责人筛选
        List<String> assignUsers=params.getAssignUsers();
        if(assignUsers!=null&&assignUsers.size()>0){
            filter.put("assign_user",assignUsers);
        }
        //按创建人筛选
        List<String> createUids=params.getCreators();
        if(createUids!=null&&createUids.size()>0){
            filter.put("uid",createUids);
        }
        //按里程碑筛选
        List<String> milepostIds=params.getMilepostIds();
        if(milepostIds!=null&&milepostIds.size()>0){
            filter.put("milepost_id",milepostIds);
        }
        //按issue开启或者关闭状态筛选：1-开;2-关
        Integer status=params.getStatus();
        if(status!=null){
            filter.put("status", ListUtil.of(status.toString()));
        }
        request.setFilter(filter);
        SearchResponse searchResponse = searchService.query_string(request);
        SearchHits hits = searchResponse.getHits();
        if(isTotal){
            long total=hits.getTotalHits().value;
            return PageDto.build(data, pageNum, pageSize, total);
        }
        SearchHit[] searchHits = hits.getHits();
        //List<String> repoIds=new ArrayList<>();
        for (SearchHit hit : searchHits) {
            Map<String, Object> map = hit.getSourceAsMap();
            IssueItemVO issueSearchVO = JSONUtil.toBean(JSON.toJSONString(map), IssueItemVO.class);
            data.add(issueSearchVO);
        }
        long total=hits.getTotalHits().value;
        return PageDto.build(data, pageNum, pageSize, total);
    }


    public PageDto<RepoSearchVO> repoSearch(RepoSearchQuery params) throws Exception{
        Boolean isTotal=params.getIsTotal();
        String key=params.getKey();
        Integer sort=params.getSort();
        Integer pageNum=params.getPageNum();
        Integer pageSize=params.getPageSize();
        List<RepoSearchVO> data = new ArrayList<>();
        ElasticSearchRequest request = new ElasticSearchRequest();
        QueryCommand query = new QueryCommand();
        query.setIndexname("repository");
        if (StringUtils.isBlank(key)) {
            query.setKeyWords("*");
        } else {
            query.setKeyWords(key);
        }
        if(!isTotal){
            query.setRows(pageSize);
            query.setStart((pageNum-1)*pageSize);
            Map<String, SortOrder> sortMap=new HashMap<>();
            switch (sort){
                case 1:
                    sortMap.put("fork_count", SortOrder.DESC);
                    break;
                case 2:
                    sortMap.put("star_count", SortOrder.DESC);
                    break;
                case 3:
                    sortMap.put("created_at", SortOrder.DESC);
                    break;
            }
            query.setSort(sortMap);
            query.setIsHighlight(true);
        }else{
            query.setRows(1);
            query.setStart(0);
        }
        query.setSearchField(repoSearchField);
        request.setQuery(query);
        //过滤条件构造
        Map<String, List<String>> filter=new HashMap<>();
        //可见性：privacy：0：私密仓库；20:公开仓库
        List<String> privacy=new ArrayList<>();
        privacy.add("20");
        filter.put("visibility_level",privacy);
        request.setFilter(filter);
        /*if (StringUtils.isNotBlank(startdate) || StringUtils.isNotBlank(enddate)) {
            FilterCommand filter = new FilterCommand();
            filter.setField("visittime");
            filter.setStartdate(startdate);
            filter.setEnddate(enddate);
            request.setFilter(filter);
        }*/
        SearchResponse searchResponse = searchService.query_string(request);
        SearchHits hits = searchResponse.getHits();
        if(isTotal){
            long total=hits.getTotalHits().value;
            return PageDto.build(data, pageNum, pageSize, total);
        }
        SearchHit[] searchHits = hits.getHits();
        List<String> projectIds=new ArrayList<>();
        for (SearchHit hit : searchHits) {
            Map<String, Object> map = hit.getSourceAsMap();
            // 获取高亮结果，对原来字段进行替换
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            for (Map.Entry<String, HighlightField> entry : highlightFields.entrySet()) {
                String mapKey = entry.getKey();
                HighlightField mapValue = entry.getValue();
                Text[] fragments = mapValue.fragments();
                String fragmentString = fragments[0].string();
                map.put(mapKey, fragmentString);
            }
            RepoSearchVO repoSearchVO = JSONUtil.toBean(JSON.toJSONString(map), RepoSearchVO.class);
            data.add(repoSearchVO);
        }
        long total=hits.getTotalHits().value;
        return PageDto.build(data, pageNum, pageSize, total);
    }
}
